#include <fstream>
#include <iostream>
#include <future>
#include <list>
#include <condition_variable>
#include <unitree/common/time/time_tool.hpp>
#include <unitree/idl/ros2/String_.hpp>
#include <unitree/robot/channel/channel_subscriber.hpp>
#include <unitree/robot/g1/audio/g1_audio_client.hpp>

struct WaveHeader {
  void SeekToDataChunk(std::istream &is) {
    while (is && subchunk2_id != 0x61746164) {
      is.seekg(subchunk2_size, std::istream::cur);
      is.read(reinterpret_cast<char *>(&subchunk2_id), sizeof(int32_t));
      is.read(reinterpret_cast<char *>(&subchunk2_size), sizeof(int32_t));
    }
  }

  int32_t chunk_id;
  int32_t chunk_size;
  int32_t format;
  int32_t subchunk1_id;
  int32_t subchunk1_size;
  int16_t audio_format;
  int16_t num_channels;
  int32_t sample_rate;
  int32_t byte_rate;
  int16_t block_align;
  int16_t bits_per_sample;
  int32_t subchunk2_id;    // a tag of this chunk
  int32_t subchunk2_size;  // size of subchunk2
};

enum {
  Play_Dialogue,
  Play_Music,
  Play_Stop
}_play_status;

class Audioplay {
public:
    Audioplay();
    ~Audioplay();

    void Init();
    void Start();
    int setVolume(uint8_t volume);
    uint8_t getVolume();
    std::vector<uint8_t> ReadWave(const std::string &filename, int32_t *sampling_rate, uint8_t *channelCount, bool *is_ok);

    std::mutex audio_mutex_;
    std::condition_variable audio_cv_;
    std::atomic<int> playsta;

    std::mutex led_mutex_;
    std::condition_variable led_cv_;
    std::atomic<bool> wakeup_;
private:
    void Play();
    void LedCtl();
    
    std::vector<std::future<void>> void_task_futures_;
    int32_t sample_rate;
    uint8_t num_channels;
    bool filestate;
    std::list<std::vector<uint8_t>> pcm_list;
    std::vector<uint8_t> ReadWaveImpl(std::istream &is, int32_t *sampling_rate, uint8_t *channelCount, bool *is_ok);
    WaveHeader header_;
    std::unique_ptr<unitree::robot::g1::AudioClient> aclient_;
};